﻿#include "EditorPopupMenuView.h"

#include "Object/NewObject.h"
#include "Widgets/Window.h"
#include "Widgets/Widget.h"
#include "Widgets/Keyboard/KeyboardWidget.h"

#include "Widgets/WidgetTree.h"

TSharedObjectPtr<RWidget> REditorPopupMenuView::ShowPopupMenu(
    const SIntPoint & InMenuSize
    , TSharedObjectPtr<RWidget> InWidgetToAround)
{
    //unfocus the current widget
    //so that the current popup window will be auto closed
    CWidgetTree::UnfocusWidget();
    assert(!PopupWindow);


    PopupWindow=NewObject<RWindow>();
    PopupWindow->HideSystemBorder();
    PopupWindow->SetWindowSize(InMenuSize);

    WidgetToAroundWeak=InWidgetToAround;
    MenuSize=InMenuSize;

    // PopupWindow->X=[WidgetToAroundWeak,InMenuSize]()->int64_t
    // {
    //     if(!WidgetToAroundWeak) 
    //     {
    //         return 0;
    //     }
        
    //     auto WorkArea=
    //         WidgetToAroundWeak->GetWindow()->GetPlacebleArea();
        
    //     auto AroundTargetArea=
    //         WidgetToAroundWeak->GetRectInScreenSpace();

    //     //at default , the popup left align with the target widget
    //     int64_t X=AroundTargetArea.Min.X;

    //     //check if the popup window is out of the screen
    //     if((AroundTargetArea.Extent.X+ AroundTargetArea.Min.X)
    //         > (WorkArea.Extent.X+ WorkArea.Min.X))
    //     {
    //         X=WorkArea.Extent.X+ WorkArea.Min.X -InMenuSize.X;
    //     }
    //     else if(AroundTargetArea.Min.X< WorkArea.Min.X)
    //     {
    //         X=WorkArea.Min.X;
    //     }

    //     return X;
    // };
    
    // PopupWindow->Y=[WidgetToAroundWeak,InMenuSize]()->int64_t
    // {
    //     if(!WidgetToAroundWeak)
    //     {
    //         return 0;
    //     }
        
    //     auto WorkArea=
    //         WidgetToAroundWeak->GetWindow()->GetPlacebleArea();
        
    //     auto AroundTargetArea=
    //         WidgetToAroundWeak->GetRectInScreenSpace();

    //     //at defualt, the popup window is below the target widget
    //     int64_t Y= AroundTargetArea.Min.Y+ AroundTargetArea.Extent.Y;

    //     int64_t BottomY= Y+ InMenuSize.Y;

    //     if( Y+ InMenuSize.Y > WorkArea.Extent.Y+ WorkArea.Min.Y)
    //     {
    //         //the popup window is out of the screen
    //         //place it above the target widget

    //         Y= AroundTargetArea.Min.Y- InMenuSize.Y;
    //     }

    //     return Y;
    // };

    UpdatePopupWindowPosition();


    PopupWindow->Show();

    auto Keybord=NewWidget<RKeyboardWidget>(PopupWindow->GetRootWidget());
    Keybord->Anchor.Fill(PopupWindow->GetRootWidget());
    Keybord->Focus();
    Keybord->OnKeyboardUnfocused.Bind([this](){
        ClosePopupMenu();
    });

    return PopupWindow->GetRootWidget();
    
}

void REditorPopupMenuView::ClosePopupMenu()
{
    if(PopupWindow)
    {
        PopupWindow->Close();
        PopupWindow=nullptr;
    }
}

void REditorPopupMenuView::Tick(float DeltaSeconds)
{
    UpdatePopupWindowPosition();
}

void REditorPopupMenuView::UpdatePopupWindowPosition()
{
    if(!WidgetToAroundWeak) 
    {
        //需要围绕的控件已经被销毁，无法计算
        return;
    }

    if(!PopupWindow)
    {
        //窗口已经关闭
        return;
    }

    auto WorkArea=
        WidgetToAroundWeak->GetWindow()->GetPlacebleArea();
        
    auto AroundTargetArea=
        WidgetToAroundWeak->GetRectInScreenSpace();

    SIntPoint PopupWindowPosition;

    //at default , the popup left align with the target widget
    PopupWindowPosition.X=AroundTargetArea.Min.X;

    //check if the popup window is out of the screen
    if((AroundTargetArea.Extent.X+ AroundTargetArea.Min.X)
        > (WorkArea.Extent.X+ WorkArea.Min.X))
    {
        PopupWindowPosition.X=WorkArea.Extent.X+ WorkArea.Min.X -MenuSize.X;
    }
    else if(AroundTargetArea.Min.X< WorkArea.Min.X)
    {
        PopupWindowPosition.X=WorkArea.Min.X;
    }


    PopupWindowPosition.Y= AroundTargetArea.Min.Y+ AroundTargetArea.Extent.Y;

    int64_t BottomY= PopupWindowPosition.Y+ MenuSize.Y;

    if( PopupWindowPosition.Y+ MenuSize.Y > WorkArea.Extent.Y+ WorkArea.Min.Y)
    {
        //the popup window is out of the screen
        //place it above the target widget

        PopupWindowPosition.Y= AroundTargetArea.Min.Y- MenuSize.Y;
    }

    PopupWindow->SetWindowPosition(PopupWindowPosition);
}
